package com.zx.security.reactive.handle;


import com.zx.core.utils.ServletUtils;
import com.zx.core.wrapper.ResponseWrapper;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * <p>
 * description: 认证失败处理类, 返回未授权  <br>
 * create: 2024-08-15 16:47
 * </p>
 *
 * @author zhou  xun
 */
@Component
public class AuthenticationEntryPointImpl implements ServerAuthenticationEntryPoint {

    /**
     * 启动身份验证流，当认证失败时返回未授权响应。
     *
     * @param exchange HTTP 访问对象，包含请求和响应信息
     * @param ex       身份验证过程中抛出的异常
     * @return Mono<Void> 指示身份验证请求处理何时完成
     */
    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException ex) {
        return Mono.defer(() -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            ResponseWrapper result = new ResponseWrapper();
            result.fail("请求访问:" + request.getPath() + "，认证失败，无法访问系统资源");
            DataBuffer buffer = ServletUtils.getDataBuffer(result, response.bufferFactory());
            return response.writeWith(Mono.just(buffer))
                    .doFinally(signalType -> DataBufferUtils.release(buffer));
        });
    }

}
